﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using WebService.DAO;
using System.Data;
using WebService.VO;

namespace WebService.BUS
{
    public class ItemBUS
    {
        ItemDAO itemDAO;
        public ItemBUS()
        {
            itemDAO = new ItemDAO();
        }

        public bool checklang(string itemid, string lang)
        {
            return itemDAO.checklang(itemid, lang);
        }

        /// <summary>
        /// Kiem tra dia diem da ton tai bang ten va vi tri cua dia diem do 
        /// </summary>
        /// <param name="name"></param>
        /// <param name="lat"></param>
        /// <param name="lng"></param>
        /// <returns></returns>
        public ItemVO getItem(string name, double lat, double lng)
        {
            return itemDAO.getItem(name, lat, lng);
        }

        /// <summary>
        /// lấy danh sách các địa điểm
        /// </summary>
        /// <returns></returns>

        public DataTable getItemsList(string language)
        {
            return itemDAO.getItemsList(language);
        }

        /// <summary>
        /// lấy danh sách các địa điểm theo loai
        /// </summary>
        /// <returns></returns>
        public DataTable getItemsList(int id, string language)
        {
            return itemDAO.getItemsList(id, language);
        }
        /// <summary>
        /// Tim kiem
        /// </summary>
        /// <param name="keyword"></param>
        /// <returns></returns>
        public DataTable search(string keyword, double latitude, double longtitude, string language)
        {
            DataTable dt =  itemDAO.getItemsList(language);
            DataTable dt1 = new DataTable();
            dt.Columns.Add("Name", typeof(String));
            foreach (DataRow DR in dt.Rows)
            {
                DR["Name"] = Utility.convertToUnSign3(DR["ItemName"].ToString());
            }
            if (keyword.Contains(','))
            {
                string[] arr = keyword.Split(',');
                string temp = Utility.convertToUnSign3(arr[0]);
                dt1 = dt.Select("Name like '%" + temp + "%'").CopyToDataTable();
            }
            else
            {
                string temp = Utility.convertToUnSign3(keyword);
                dt1 = dt.Select("Name like '%" + temp + "%'").CopyToDataTable();
            }
            
            dt1.Columns.Remove("Name");
            List<DataRow> rowsToDelete = new List<DataRow>();
            double distance = 0;
            double R = 6371;
            double deltaLatitude = 0;
            double deltaLongtitude = 0;
            double a = 0;
            double c = 0;
            double dLatitude1 = 0;
            double dLongtitude1 = 0;
            double dLatitude2 = 0;
            double dLongtitude2 = 0;
            dt1.Columns.Add("Distance", typeof(Double));
            //values of latitude converted to Radian
            dLatitude1 = Convert.ToDouble(latitude) * Math.PI / 180;
            //values of longtitude converted to Radian
            dLongtitude1 = Convert.ToDouble(longtitude) * Math.PI / 180;
            foreach (DataRow DR in dt1.Rows)
            {
                //values of Latitude in database converted to Radian
                dLatitude2 = Convert.ToDouble(DR["X"].ToString()) * Math.PI / 180;
                //values of Longtitude in database converted to Radian
                dLongtitude2 = Convert.ToDouble(DR["Y"].ToString()) * Math.PI / 180;
                //values of Delta Latitude
                deltaLatitude = (dLatitude2 - dLatitude1);
                //values of Delta Longtitude
                deltaLongtitude = (dLongtitude2 - dLongtitude1);
                //a = sin²(Δlat/2) + cos(lat1).cos(lat2).sin²(Δlong/2)
                a = Math.Pow(Math.Sin(deltaLatitude / 2), 2) + Math.Cos(dLatitude2) * Math.Cos(dLatitude1) * Math.Pow(Math.Sin(deltaLongtitude / 2), 2);
                //c = 2.atan2(√a, √(1−a))
                c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
                //d = R.c
                distance = R * c;
                DR["Distance"] = distance;
                // conditional of distance <= scope KM
                if (distance > 10)
                    rowsToDelete.Add(DR);
            }

            foreach (var rw in rowsToDelete)
                dt1.Rows.Remove(rw);
            foreach (DataRow row in dt1.Rows)
            {
                for (int i = 0; i < dt1.Columns.Count; i++)
                {


                    dt1.Columns[i].ReadOnly = false;

                    if (string.IsNullOrEmpty(row[i].ToString()))
                    {
                        if (dt1.Columns[i].DataType == typeof(string))
                            row[i] = "NULL";
                        else if (dt1.Columns[i].DataType == typeof(int))
                            row[i] = new int();
                        else if (dt1.Columns[i].DataType == typeof(DateTime))
                            row[i] = new DateTime();
                    }
                }
            }
            dt1.DefaultView.Sort = "DISTANCE ASC";
            dt1 = dt1.DefaultView.ToTable();
            //dt.Columns.Remove("Distance");
            return dt1;
        }
        
        /// <summary>
        /// lay thong tin mot dia diem
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public ItemVO getItems(string id, string language)
        {
            return itemDAO.getItem(id, language);
        }

        /// <summary>
        /// lấy danh sách các địa điểm trong bán kính R
        /// </summary>
        /// <returns></returns>

        public DataTable getItemsList(double latitude, double longtitude,double r, string language)
        {
            DataTable dt = itemDAO.getItemsList(language);
            List<DataRow> rowsToDelete = new List<DataRow>();
            double distance = 0;
            double R = 6371;
            double deltaLatitude = 0;
            double deltaLongtitude = 0;
            double a = 0;
            double c = 0;
            double dLatitude1 = 0;
            double dLongtitude1 = 0;
            double dLatitude2 = 0;
            double dLongtitude2 = 0;
            dt.Columns.Add("Distance", typeof(Double));
            //values of latitude converted to Radian
            dLatitude1 = Convert.ToDouble(latitude) * Math.PI / 180;
            //values of longtitude converted to Radian
            dLongtitude1 = Convert.ToDouble(longtitude) * Math.PI / 180;
            foreach (DataRow DR in dt.Rows)
            {
                //values of Latitude in database converted to Radian
                dLatitude2 = Convert.ToDouble(DR["X"].ToString()) * Math.PI / 180;
                //values of Longtitude in database converted to Radian
                dLongtitude2 = Convert.ToDouble(DR["Y"].ToString()) * Math.PI / 180;
                //values of Delta Latitude
                deltaLatitude = (dLatitude2 - dLatitude1);
                //values of Delta Longtitude
                deltaLongtitude = (dLongtitude2 - dLongtitude1);
                //a = sin²(Δlat/2) + cos(lat1).cos(lat2).sin²(Δlong/2)
                a = Math.Pow(Math.Sin(deltaLatitude / 2), 2) + Math.Cos(dLatitude2) * Math.Cos(dLatitude1) * Math.Pow(Math.Sin(deltaLongtitude / 2), 2);
                //c = 2.atan2(√a, √(1−a))
                c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
                //d = R.c
                distance = R * c;
                DR["Distance"] = distance;
                // conditional of distance <= scope KM
                if (distance > r)
                    rowsToDelete.Add(DR);
            }

            foreach (var rw in rowsToDelete)
                dt.Rows.Remove(rw);
            foreach (DataRow row in dt.Rows)
            {
                for (int i = 0; i < dt.Columns.Count; i++)
                {


                    dt.Columns[i].ReadOnly = false;

                    if (string.IsNullOrEmpty(row[i].ToString()))
                    {
                        if (dt.Columns[i].DataType == typeof(string))
                            row[i] = "NULL";
                        else if (dt.Columns[i].DataType == typeof(int))
                            row[i] = new int();
                        else if (dt.Columns[i].DataType == typeof(DateTime))
                            row[i] = new DateTime();
                    }
                }
            }
            dt.DefaultView.Sort = "Distance ASC";
            dt = dt.DefaultView.ToTable();
            //dt.Columns.Remove("Distance");
            return dt;
        }


        /// <summary>
        /// lấy danh sách các địa điểm trong bán kính R
        /// </summary>
        /// <returns></returns>

        public DataTable getItemsList(DataTable dt, double latitude, double longtitude, double r)
        {
            List<DataRow> rowsToDelete = new List<DataRow>();
            double distance = 0;
            double R = 6371;
            double deltaLatitude = 0;
            double deltaLongtitude = 0;
            double a = 0;
            double c = 0;
            double dLatitude1 = 0;
            double dLongtitude1 = 0;
            double dLatitude2 = 0;
            double dLongtitude2 = 0;
            //values of latitude converted to Radian
            dLatitude1 = Convert.ToDouble(latitude) * Math.PI / 180;
            //values of longtitude converted to Radian
            dLongtitude1 = Convert.ToDouble(longtitude) * Math.PI / 180;
            foreach (DataRow DR in dt.Rows)
            {
                //values of Latitude in database converted to Radian
                dLatitude2 = Convert.ToDouble(DR["X"].ToString()) * Math.PI / 180;
                //values of Longtitude in database converted to Radian
                dLongtitude2 = Convert.ToDouble(DR["Y"].ToString()) * Math.PI / 180;
                //values of Delta Latitude
                deltaLatitude = (dLatitude2 - dLatitude1);
                //values of Delta Longtitude
                deltaLongtitude = (dLongtitude2 - dLongtitude1);
                //a = sin²(Δlat/2) + cos(lat1).cos(lat2).sin²(Δlong/2)
                a = Math.Pow(Math.Sin(deltaLatitude / 2), 2) + Math.Cos(dLatitude2) * Math.Cos(dLatitude1) * Math.Pow(Math.Sin(deltaLongtitude / 2), 2);
                //c = 2.atan2(√a, √(1−a))
                c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
                //d = R.c
                distance = R * c;
                DR["Distance"] = distance;
                // conditional of distance <= scope KM
                if (distance > r)
                    rowsToDelete.Add(DR);
            }

            foreach (var rw in rowsToDelete)
                dt.Rows.Remove(rw);
            foreach (DataRow row in dt.Rows)
            {
                for (int i = 0; i < dt.Columns.Count; i++)
                {


                    dt.Columns[i].ReadOnly = false;

                    if (string.IsNullOrEmpty(row[i].ToString()))
                    {
                        if (dt.Columns[i].DataType == typeof(string))
                            row[i] = "NULL";
                        else if (dt.Columns[i].DataType == typeof(int))
                            row[i] = new int();
                        else if (dt.Columns[i].DataType == typeof(DateTime))
                            row[i] = new DateTime();
                    }
                }
            }
            dt.DefaultView.Sort ="Distance ASC";
            dt = dt.DefaultView.ToTable();
            //dt.Columns.Remove("Distance");
            return dt;
        }


        /// <summary>
        /// lấy danh sách các địa điểm trong bán kính R
        /// </summary>
        /// <returns></returns>

        public DataTable getItemsList(double latitude, double longtitude, double r, int id, string deviceid, string language)
        {
            DataTable dt = itemDAO.getItemsList(id, language);
            List<DataRow> rowsToDelete = new List<DataRow>();
            double distance = 0;
            double R = 6367;
            double deltaLatitude = 0;
            double deltaLongtitude = 0;
            double a = 0;
            double c = 0;
            double dLatitude1 = 0;
            double dLongtitude1 = 0;
            double dLatitude2 = 0;
            double dLongtitude2 = 0;
            dt.Columns.Add("Distance", typeof(Double));
            //values of latitude converted to Radian
            dLatitude1 = Convert.ToDouble(latitude) * Math.PI / 180;
            //values of longtitude converted to Radian
            dLongtitude1 = Convert.ToDouble(longtitude) * Math.PI / 180;
            foreach (DataRow DR in dt.Rows)
            {
                //values of Latitude in database converted to Radian
                dLatitude2 = Convert.ToDouble(DR["X"].ToString()) * Math.PI / 180;
                //values of Longtitude in database converted to Radian
                dLongtitude2 = Convert.ToDouble(DR["Y"].ToString()) * Math.PI / 180;
                //values of Delta Latitude
                deltaLatitude = (dLatitude2 - dLatitude1);
                //values of Delta Longtitude
                deltaLongtitude = (dLongtitude2 - dLongtitude1);
                //a=sin²(Δlat/2) + cos(lat1).cos(lat2).sin²(Δlong/2)
                a = Math.Pow(Math.Sin(deltaLatitude / 2), 2) + Math.Cos(dLatitude2) * Math.Cos(dLatitude1) * Math.Pow(Math.Sin(deltaLongtitude / 2), 2);
                //c = 2.atan2(√a, √(1−a))
                c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
                //d = R.c
                distance = R * c;
                DR["Distance"]=distance;
                // conditional of distance <= scope KM
                if (distance > r)
                    rowsToDelete.Add(DR);
            }

            foreach (var rw in rowsToDelete)
                dt.Rows.Remove(rw);
            foreach (DataRow row in dt.Rows)
            {
                for (int i = 0; i < dt.Columns.Count; i++)
                {


                    dt.Columns[i].ReadOnly = false;

                    if (string.IsNullOrEmpty(row[i].ToString()))
                    {
                        if (dt.Columns[i].DataType == typeof(string))
                            row[i] = "NULL";
                        else if (dt.Columns[i].DataType == typeof(int))
                            row[i] = new int();
                        else if (dt.Columns[i].DataType == typeof(DateTime))
                            row[i] = new DateTime();
                    }
                }
            }
            dt = dt.AsEnumerable().Skip(0).Take(50).CopyToDataTable();
            dt.DefaultView.Sort = "Distance ASC";
            dt = dt.DefaultView.ToTable();
            //dt.Columns.Remove("Distance");
            return dt;
        }

        /// <summary>
        /// Thêm mới 1 địa điểm
        /// </summary>
        public bool insert(ItemVO item)
        {
            if (!itemDAO.check(item.ItemName, item.X.ToString(), item.Y.ToString(), item.Category.CategoryId))
            {
                itemDAO.insert(item);
                return true;
            }
            return false;
        }

        /// <summary>
        /// Cập nhật 1 địa điểm
        /// </summary>
        public bool update(ItemVO item)
        {
            if (itemDAO.check(item.ItemName, item.X.ToString(), item.Y.ToString(),item.Category.CategoryId))
            {
                itemDAO.update(item);
                return true;
            }
            return false;

        }

        /// <summary>
        /// Xóa thông tin một địa điểm
        /// </summary>
        public void delete(string id)
        {
            itemDAO.delete(id);
        }


        public int insertFromTbl(DataTable dt, int id)
        {
            int i = 0;
            foreach (DataRow row in dt.Rows)
            {
                if (itemDAO.check(row["Name"].ToString(), row["Lat"].ToString(), row["Lng"].ToString(), id) != true)
                {
                    i++;
                    ItemVO item = new ItemVO();
                    item.ItemName = row["Name"].ToString();
                    CategoryVO cate = new CategoryVO();
                    cate.CategoryId = id;
                    cate.CategoryName = "";
                    item.Category = cate;
                    item.CountRate = 0;
                    item.Rate = 0;
                    item.Phone = "";
                    item.Note = "";
                    item.Image = "";
                    item.Email = "";
                    item.X = Convert.ToDouble(row["Lat"]);
                    item.Y = Convert.ToDouble(row["Lng"]);
                    item.Address = row["Vicinity"].ToString();
                    item.Check = 1;
                    itemDAO.insert(item);
                }
            }
            return i;
        }
    }
}